﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using LiveCPEWinForm.LiveCPEWS;
using System.Windows.Forms;
using System.IO;

namespace LiveCPEWinForm.Gestionnaire
{
    public class GestAPP
    {
        /***************************** Gestion spécifique des evenements ************************/
        // Type Argument spécifique
        public class ChangeEventArgs : EventArgs 
        {
                public String StatusString;
                public int StatusCode;
        }
        public class ChangeEventUserArgs : EventArgs
        {
            public UserWS User;
        }
        public class ChangeMessageEventArgs : EventArgs
        {
            public List<GestMessage> ListMessages;
            public bool Reload;
        }
        // Type
        public delegate void StatusChange(object sender, ChangeEventArgs e);
        public delegate void UserChange(object sender, ChangeEventUserArgs e);
        public delegate void WorkInProgress(object sender, EventArgs e);
        public delegate void MessageChange(object sender, ChangeMessageEventArgs e);
        // Evenement
        public event StatusChange Changed;
        public event UserChange UserChanged;
        public event WorkInProgress WrkInProg;
        public event MessageChange MessageChanged;
        // fonction su changement d'utilisateur
        protected virtual void OnUserChange()
        {
            ChangeEventUserArgs evt = new ChangeEventUserArgs();
            evt.User = lUser;
            if (UserChanged != null)
                UserChanged(this, evt);
        }
        // Fonction local
        protected virtual void OnChanged()
        {
            ChangeEventArgs evt = new ChangeEventArgs();
            evt.StatusCode = lConnectState;
            evt.StatusString = lConnectionStatus;
            if (Changed != null)
                Changed(this, evt);
        }
        // Fonction sur Evenement en cours de chargement
        protected virtual void OnWorkInProgress()
        {
            EventArgs evt = new EventArgs();
            if(WrkInProg != null)
                WrkInProg(this,evt);
        }
        // Fonction si changement dans liste message
        protected virtual void OnMessageChanged(List<GestMessage> pNewMessage)
        {
            if(lGestMessages.Count() != pNewMessage.Count()||(lForceReload))
            {
                // Chargement evenement
                ChangeMessageEventArgs evt= new ChangeMessageEventArgs();
                evt.ListMessages = pNewMessage;
                evt.Reload = lForceReload;
                lGestMessages = pNewMessage;
                // Raise event
                if(MessageChanged != null)
                    MessageChanged(this,evt);
            }
            // Nouvelle liste de message
            lGestMessages = pNewMessage;
            lForceReload = false;
        }
        /****************************************************************************************/
        // Reload Action defini si la fenetre doit se rafraichir en Auto
        bool lForceReload;
        // Lien vers le webservice
        private LiveCPEWS.Service1Client lService;
        public LiveCPEWS.Service1Client Service
        {
            get { return lService; }
            set { lService = value; }
        }
        private int lLastRefresh;
        // Timer de rafrachissement de message
        private Timer lTimerRefresh;
        private void OnTimerTick(Object sender, EventArgs e)
        {
            // Génération evenement En cours de traitement
            if (ConnectState == 2)
            {
                OnWorkInProgress();
            }
            else
            {
                if (lLastRefresh > 4)
                {
                    // Récupération des messages Si Pas d'opération EC
                    if (lUser != null) GetMessages();
                    lLastRefresh = 0;
                }
                else
                    lLastRefresh += 1;

            }
        }
        // Status de connexion
        private int lConnectState;
        public int ConnectState
        {
            get { return lConnectState; }
        }

        private string lUserName;
        private string lPassword;
        private UserWS lUser;
        // Accès Amis
        private GestFriend lGestFriend;
        public GestFriend GestFriends
        {
            get { return lGestFriend; }
            set { lGestFriend = value; }
        }
        // Image
        private System.Drawing.Image lImg;
        public System.Drawing.Image img
        {
            get { return lImg; }
        }
        public UserWS user
        {
            get { return lUser; }
        }

        private List<GestMessage> lGestMessages;

        public List<GestMessage> GestMessages
        {
            get { return lGestMessages; }
        }

        private String lConnectionStatus;

        public String ConnectionStatus
        {
            get { return lConnectionStatus; }
        }

        public string Password
        {
            get { return lPassword; }
            set { lPassword = value; }
        }

        public string UserName
        {
            get { return lUserName; }
            set { lUserName = value; }
        }

        // **************************************************  Constructeur
        public GestAPP()
        {
            lService = new LiveCPEWS.Service1Client();
            lGestMessages = new List<GestMessage>();
            lConnectState = 0;
            lForceReload = false;
            // Initialisation des Evenements
            lService.GetMessagesCompleted += new EventHandler<GetMessagesCompletedEventArgs>(lService_GetMessagesCompleted);
            lService.DoLoginCompleted += new EventHandler<DoLoginCompletedEventArgs>(lService_DoLoginCompleted);
            lService.GetUserCompleted += new EventHandler<GetUserCompletedEventArgs>(lService_GetUserCompleted);
            lService.CreateUserCompleted += new EventHandler<CreateUserCompletedEventArgs>(lService_CreateUserCompleted);
            lService.UpdateUserCompleted += new EventHandler<UpdateUserCompletedEventArgs>(lService_UpdateUserCompleted);
            lService.SendPublicMessageCompleted += new EventHandler<SendPublicMessageCompletedEventArgs>(lService_SendPublicMessageCompleted);
            lService.SendPrivateMessageCompleted += new EventHandler<SendPrivateMessageCompletedEventArgs>(lService_SendPrivateMessageCompleted);
            lService.SendCommentCompleted += new EventHandler<SendCommentCompletedEventArgs>(lService_SendCommentCompleted);
            lService.LikeCommentCompleted += new EventHandler<LikeCommentCompletedEventArgs>(lService_LikeCommentCompleted);
            lService.LikeMessageCompleted += new EventHandler<LikeMessageCompletedEventArgs>(lService_LikeMessageCompleted);
            // Gestionnaire de friend
            lGestFriend = new GestFriend(this);
            lGestFriend.OnFriendRefresh += new GestFriend.FriendsLoaded(lGestFriend_OnFriendRefresh);
        }
        void lGestFriend_OnFriendRefresh(object sender, EventArgs e)
        {
            lForceReload = true;
        }
        public void InitTimer()
        {
            // Création du timer
            lTimerRefresh = new Timer();
            lTimerRefresh.Interval = 1000;
            lTimerRefresh.Tick += new EventHandler(OnTimerTick);
            // Activation
            lTimerRefresh.Enabled = true;
        }

        // Peuplement du gestionnaire de message
        public void GetMessages()
        {
            lService.GetMessagesAsync();
            // Gestion message
            lConnectionStatus = "Loading message for " + lUser.UserName + ".";
            lConnectState = 2;
            // Changement
            OnChanged();
        }

        void lService_GetMessagesCompleted(object sender, GetMessagesCompletedEventArgs e)
        {
            try
            {
                List<GestMessage> lList = new List<GestMessage>(); 
                foreach (MessageWS msg in e.Result)
                {
                    GestMessage ges = new GestMessage(this, msg);
                    lList.Add(ges);
                }
                lConnectionStatus = "Loading done.";
                // Evenement Nouveau message
                OnMessageChanged(lList);
            }
            catch (Exception ex) {
                lConnectionStatus = "Loading Failed. "+ex.Message;
            }
            // Mode connecté
            lConnectState = 1;
            // Changement
            OnChanged();
        }


        // Login de base
        public void doLogin(String pUsername, String pPassword)
        {
            // Sauvegarde du contexte
            lUserName = pUsername;
            lPassword = pPassword;
            // Methode assync
            lService.DoLoginAsync(lUserName, lPassword);
            lConnectionStatus = "Login procedure. Please wait.";
            // EC
            lConnectState = 2;
            // EVT
            OnChanged();
        }
        // Lor fin de connexion
        private void lService_DoLoginCompleted(object sender, LiveCPEWS.DoLoginCompletedEventArgs e)
        {
            if (e.Result)
            {
                // msg status
                lConnectionStatus = "Login OK.";
                // Recupération user courant
                lService.GetUserAsync();
            }
            else
            {
                lConnectState = 0;
                lUserName = "";
                lPassword = "";
                lConnectionStatus = "Connection Fault.";
            }
            OnChanged();
        }

        void lService_GetUserCompleted(object sender, LiveCPEWS.GetUserCompletedEventArgs e)
        {
            try
            {
                lUser = e.Result;
                if (lUser != null)
                {
                    // Récupération assync des messages
                    GetMessages();
                    // Recupere l'image du profil
                    lImg = GetUserPicture();
                    // REcupere les amis
                    lGestFriend.UpdateFriend();
                }
                // Evenement sur le changement d'utilisateur
                OnUserChange();
                lConnectState = 1;
                lConnectionStatus = "User OK.";
            }
            catch (Exception)
            {
                doDisconnect();
            }

        }
        // Récupération de l'image du profil
        private System.Drawing.Image GetUserPicture()
        {
            try
            {
                Byte[] tb = lService.GetUserPicture();
                System.IO.MemoryStream ms = new System.IO.MemoryStream(tb);
                return System.Drawing.Image.FromStream(ms);
            }
            catch (Exception)
            {
                return null;
            }
        }
        // Récupération de l'image du profil
        private System.Drawing.Image GetPictureByUser(String pUserName)
        {
            try
            {
                Byte[] tb = lService.GetUserPictureByUser(pUserName);
                System.IO.MemoryStream ms = new System.IO.MemoryStream(tb);
                return System.Drawing.Image.FromStream(ms);
            }
            catch (Exception)
            {
                return null;
            }
        }
        // Deconnexion
        public void doDisconnect()
        {
            // Suppression de la session
            lService.DoDisconnectAsync();
            lConnectionStatus = "";
            lConnectState = 0;
            lUser = null;
            lUserName = "";
            lPassword = "";
            lGestMessages.Clear();
            // EVT
            OnChanged();
        }
        // Creation d'un nouvel utilisateur
        public void CreateUser(UserWS pUser)
        {
            // Deconnexion par défaut
            doDisconnect();
            // Sauvegarde pour l'image
            lUser = pUser;
            UserWS usr = new UserWS();
            usr.FirstName = pUser.FirstName;
            usr.LastName = pUser.LastName;
            usr.DateOfBirth = pUser.DateOfBirth;
            usr.Email = pUser.Email;
            usr.Gender = pUser.Gender;
            usr.Password = pUser.Password;
            usr.UserName = pUser.UserName;
            // Access WS
            lService.CreateUserAsync(usr);
            // EC
            lConnectState = 2;
            lConnectionStatus = "User creation. Please wait.";
            // Evt
            OnChanged();
        }
        // Fin de procedure Assynchrone
        void lService_CreateUserCompleted(object sender, CreateUserCompletedEventArgs e)
        {
            // Mode déconnecté
            lConnectState = 0;
            try
            {
                lConnectionStatus = e.Result;
                // Ajout de l'image
                try
                {
                    lService.UpdateImage(lUser.UserName, lUser.Picture);
                }
                catch (Exception) { }
            }
            catch (Exception ex)
            {
                lConnectionStatus = "Error : " + ex.Message;
            }
            lUser = null;
            // Evt
            OnChanged();
        }
        // Mise à jour d'utilisateur
        public void UpdateUser(UserWS pUser)
        {
            // Accèss WS
            lService.UpdateUserAsync(pUser);
            // Changement d'état
            // EC
            lConnectState = 2;
            lConnectionStatus = "User upgrade. Please wait.";
            // Evt
            OnChanged();
        }

        void lService_UpdateUserCompleted(object sender, UpdateUserCompletedEventArgs e)
        {
            try
            {
                lConnectionStatus = e.Result;
                doLogin(lUserName, lPassword);
            }
            catch (Exception ex)
            {
                doDisconnect();
                lConnectionStatus = "Error : " + ex.Message;
            }
            // Evt
            OnChanged();            
        }
        //************************************************** Manipulation de message
        public void SendPublicMessage(String pDest, String pContent)
        {
            lService.SendPublicMessageAsync(pDest, pContent);
            // Wrk in Progress
            lConnectionStatus = "Sending Public Message...";
            lConnectState = 2;
            OnChanged();
        }

        void lService_SendPublicMessageCompleted(object sender, SendPublicMessageCompletedEventArgs e)
        {
            lConnectState = 1;
            try
            {
                if (e.Result) { 
                    lConnectionStatus = "Message Sended.";
                    // Force Reload Page
                    lForceReload = true;
                }
            }
            catch (Exception ex)
            {
                lConnectionStatus = ex.Message;
            }
        }


        public void SendPrivateMessage(String pDest, String pContent)
        {

            lService.SendPrivateMessageAsync(pDest, pContent);
            // Wrk in Progress
            lConnectionStatus = "Sending Private Message...";
            lConnectState = 2;
            OnChanged();
        }

        void lService_SendPrivateMessageCompleted(object sender, SendPrivateMessageCompletedEventArgs e)
        {
            lConnectState = 1;
            try
            {
                if (e.Result) 
                { 
                    lConnectionStatus = "Message Sended.";
                    // Force Reload Page
                    lForceReload = true;
                }
            }
            catch (Exception ex)
            {
                lConnectionStatus = ex.Message;
            }

        }
        public void SendComment(String pMessID, String pContent)
        {
            lService.SendCommentAsync(pMessID,pContent);
            // Wrk in Progress
            lConnectionStatus = "Sending Comment...";
            lConnectState = 2;
            OnChanged();
        }
        void lService_SendCommentCompleted(object sender, SendCommentCompletedEventArgs e)
        {
            lConnectState = 1;
            try
            {
                if (e.Result) 
                { 
                    lConnectionStatus = "Comment Sended.";
                    // Force Reload Page
                    lForceReload = true;
                }
            }
            catch (Exception ex)
            {
                lConnectionStatus = ex.Message;
            }
        }
        public void LikeMessage(String pMessID)
        {
            lService.LikeMessageAsync(pMessID);
            // Wrk in Progress
            lConnectionStatus = "Add Like to Message...";
            lConnectState = 2;
            OnChanged();
        }

        void lService_LikeMessageCompleted(object sender, LikeMessageCompletedEventArgs e)
        {
            lConnectState = 1;
            try
            {
                if (e.Result) 
                { 
                    lConnectionStatus = "Like Message added.";
                    // Force Reload Page
                    lForceReload = true;
                }
            }
            catch (Exception ex)
            {
                lConnectionStatus = ex.Message;
            }
        }
        public void LikeComment(String pCommID)
        {
            lService.LikeCommentAsync(pCommID);
            // Wrk in Progress
            lConnectionStatus = "Add Like to Comment...";
            lConnectState = 2;
            OnChanged();
        }

        void lService_LikeCommentCompleted(object sender, LikeCommentCompletedEventArgs e)
        {
            lConnectState = 1;
            try
            {
                if (e.Result) 
                { 
                    lConnectionStatus = "Like Comment added.";
                    // Force Reload Page
                    lForceReload = true;
                }
            }
            catch (Exception ex)
            {
                lConnectionStatus = ex.Message;
            }
        }

        public String AcceptFriendShip(String pMessageId)
        {
            lForceReload = true;
            return lGestFriend.AcceptFriend(pMessageId);
        }
        public String RejectFriendShip(String pMessageId)
        {
            lForceReload = true;
            return lGestFriend.RejectFriend(pMessageId);
        }
        public void SetImage(String pUsername, System.Drawing.Image img)
        {
            try
            {
                MemoryStream ms = new MemoryStream();
                img.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
                lService.UpdateImage(pUsername, ms.ToArray());
                // Recupération
                lImg = GetPictureByUser(pUsername);
            }
            catch (Exception) { }
        }
        
    }
}
